#ifndef QQTUSERONLINEMANAGER_H
#define QQTUSERONLINEMANAGER_H

#include <QObject>
#include <QTimer>

#include <qqtudpclient.h>
#include <qqtudpserver.h>

#include <qqtprotocol.h>
#include <qqtprotocolmanager.h>
#include <qqtdataprotocol.h>
#include <qqtfindservermanager.h>

#include <qqtframe.h>

#include <qqthighgrade_global.h>

class QQtUserOnlineServerProtocolManager;
class QQtUserOnlineServerProtocol;
class QQtUserOnlineProtocol;

/**
 * @brief The QQtUserOnlineServerManager class
 * 广域网在线用户列表 服务器端
 *
 * 如果用户更改本地IP，需要重启服务端。
 */
class QQTHIGHGRADESHARED_EXPORT QQtUserOnlineServerManager: public QObject
{
    Q_OBJECT

public:
    explicit QQtUserOnlineServerManager ( QObject* parent = 0 );
    virtual ~QQtUserOnlineServerManager();

    void setListeningAddress ( QHostAddress address, int port = 4412 );
    void setListeningPort ( int port = 4412 );

    void setUserName ( QString username );
    void setUserContent ( QString key, QString content );

    QString getUserName();

    QString getUserContent ( QString key );

    QQtDictionary& userDict();

signals:
    void signalUserInformationChanged ( const QQtDictionary& );
protected:
    void setLocalIpPort ( QString ip, int port );
    void setUUid ( QString uuid );

protected slots:
    void remainingProtocolChanged ( int );

protected:

private:
    QString mIP;
    int mPort;
    QString mUUid;
    QString mUserName;
    QQtDictionary mUserContent;

    QQtUdpServer* s0;
    QQtUserOnlineServerProtocolManager* m0;
};

/**
 * @brief The QQtUserOnlineManager class
 * 广域网在线用户列表 客户端
 */
class QQTHIGHGRADESHARED_EXPORT QQtUserOnlineManager: public QObject
{
    Q_OBJECT

public:
    explicit QQtUserOnlineManager ( QObject* parent = 0 );
    virtual ~QQtUserOnlineManager();

    void setServerAddress ( QHostAddress address, int port = 4412 );

    void setListeningAddress ( QHostAddress address, int port = 4411 );
    void setListeningPort ( int port = 4411 );

    void setUserName ( QString username );
    void setUserContent ( QString key, QString content );

    void sendRequestServerInformation();
    void sendRequestUserInformation();
    void sendInformation();
    void sendLogin();
    void sendLogout();


signals:
    void signalServerInformation ( const QQtDictionary& );
    void signalUserInformation ( const QQtDictionary& );

protected:
    void setLocalIpPort ( QString ip, int port );
    void setUUid ( QString uuid );

protected slots:

protected:

private:
    QString mIP;
    int mPort;
    QString mUUid;
    QString mUserName;
    QQtDictionary mUserContent;

    QQtUdpClient* c0;
    QQtUserOnlineProtocol* p0;
};

/**
 * @brief The QQtUserOnlineServerProtocolManager class
 */
class QQTHIGHGRADESHARED_EXPORT QQtUserOnlineServerProtocolManager : public QQtProtocolManager
{
    Q_OBJECT
public:
    explicit QQtUserOnlineServerProtocolManager ( QObject* parent = 0 );
    virtual ~QQtUserOnlineServerProtocolManager();

    void setLocalIpPort ( QString ip, int port );
    void setUUid ( QString uuid );
    void setUserName ( QString username );
    void setUserContent ( QString key, QString content );

    QQtDictionary& getUserDict();

signals:
    void signalUserInformationChanged ( const QQtDictionary& dictUser );

private slots:
    void slotRecvUserInformation ( const QQtDictionary& data );
    void slotProcessingUserRequest ( const QQtProtocol* self, const QQtMessage* message );

    void slotTimeout();

private:
    QString mIP;
    int mPort;
    QString mUUid;
    QString mUserName;
    QQtDictionary mUserContent;

    QQtDictionary mDictUser;

    QTimer* m_timer;

    // QQtProtocolManager interface
public:
    virtual QQtProtocol* createProtocol() override;
};

/**
 * @brief The QQtUserOnlineServerProtocol class
 * 广域网用户在线状态调查服务器端
 *
 * [0] "login"
 * [0] "logout"
 * [0] "information"
 *
 * [0] "req_information"
 * [1]  ["ip"] =
 *      ["port"] =
 *      ["uuid"] =
 *      ["user_name"] =
 *      ["user_content"] [...] =
 *      ["heartbeats"] = 1
 *
 * [0] "rsp_information"
 * [1]
 *      ["uuid"]
 *          ["ip"] =
 *          ["port"] =
 *          ["user_name"] =
 *          ["user_content"] [...] =
 *          ["heartbeats"] = 1
 *
 * [0] "req_server_information"
 * [1]  ["ip"] =
 *      ["port"] =
 *      ["uuid"] =
 *      ["user_name"] =
 *      ["user_content"] [...] =
 *      ["heartbeats"] = 1
 *
 * [0] "rsp_server_information"
 * [1]  ["ip"] =
 *      ["port"] =
 *      ["uuid"] =
 *      ["user_name"] =
 *      ["user_content"] [...] =
 *      ["heartbeats"] = 1
 */
class QQTHIGHGRADESHARED_EXPORT QQtUserOnlineServerProtocol : public QQtDataProtocol
{
    Q_OBJECT
public:
    explicit QQtUserOnlineServerProtocol ( QObject* parent = 0 );
    virtual ~QQtUserOnlineServerProtocol();

    void setIPPort ( QString ip, int port );
    void setUUid ( QString uuid );
    void setUserName ( QString username );
    void setUserContent ( QString key, QString content );

    void recvUserInformation ( const QQtDictionary& data );


    void recvReqServerInformation();

    void sendServerInformation();

    void recvReqInformation ( const QQtDataSerialization& message );

    void sendRspInformation ( const QQtDictionary& dictUser );

signals:
    void signalRecvUserInformation ( const QQtDictionary& data );

private:
    QString mIP;
    int mPort;
    QString mUUid;
    QString mUserName;
    QQtDictionary mUserContent;

    // QQtDataProtocol interface
public:
    virtual void recvMessage ( const QQtDataSerialization& data ) override;
};

/**
 * @brief The QQtUserOnlineProtocol class
 * 广域网用户在线统计协议。
 *
 * [0] "logout"
 * [1]  ["ip"] =
 *      ["port"] =
 *      ["uuid"] =
 *      ["user_name"] =
 *      ["user_content"] [...] =
 *      ["heartbeats"] = 0
 *
 * [0] "login"
 * [1]  ["ip"] =
 *      ["port"] =
 *      ["uuid"] =
 *      ["user_name"] =
 *      ["user_content"] [...] =
 *      ["heartbeats"] = 1
 *
 * [0] "information"
 * [1]  ["ip"] =
 *      ["port"] =
 *      ["uuid"] =
 *      ["user_name"] =
 *      ["user_content"] [...] =
 *      ["heartbeats"] = 1
 */
class QQTHIGHGRADESHARED_EXPORT QQtUserOnlineProtocol : public QQtDataProtocol
{
    Q_OBJECT
public:
    explicit QQtUserOnlineProtocol ( QObject* parent = 0 );
    virtual ~QQtUserOnlineProtocol();


    void setIPPort ( QString ip, int port );
    void setUUid ( QString uuid );
    void setUserName ( QString username );
    void setUserContent ( QString key, QString content );

    //这两个有必要调用。
    void sendLogin();
    void sendLogout();

    void sendInformation();

    void sendHeartbeats();

    void sendReqInformation();

    void sendReqServerInformation();

signals:
    void signalUserInformation ( const QQtDictionary& );
    void signalServerInformation ( const QQtDictionary& );

protected slots:
    void slotTimeout();

private:
    QString mIP;
    int mPort;
    QString mUUid;
    QString mUserName;
    QQtDictionary mUserContent;

    QTimer* m_timer;

    // QQtDataProtocol interface
public:
    virtual void recvMessage ( const QQtDataSerialization& data ) override;
};

#endif // QQTUSERONLINEMANAGER_H

